<?php

namespace App\Http\Controllers\Api;

use App\GameChannel\SdkBase;
use App\Http\Controllers\Controller;
use App\Jobs\PayGameCbQueue;
use App\Jobs\PaySuccessQueue;
use App\Models\GameChannelGoodsId;
use App\Models\Log\LogPayCb;
use App\Models\Orders;
use App\Models\Users;
use App\Services\GameChannelService;
use App\Services\OrdersCallClientService;
use App\Services\PayService;
use App\Services\SdkService;
use App\Services\UserRoleUniqueIdService;
use Illuminate\Http\Request;
use YQ\YqExtend;

class PayController extends Controller
{
    public function create(Request $request)
    {
        $params = $request->all();

        // 校验签名
        $ret = SdkService::getInstance()->checkSign($params);
        if ($ret === false) {
            return yqerr(101);
        }

        $game_id         = $params['game_id'];
        $channel         = $params['channel'];
        $package_id      = $params['package_id'] ?? 0;
        $user_id         = $params['user_id'];
        $game_trade_no   = $params['game_trade_no'];
        $amount          = $params['amount'];
        $money           = $amount;
        $goods_id        = $params['goods_id'];
        $goods_name      = $params['goods_name'];
        $server_id       = $params['server_id'];
        $server_name     = $params['server_name'] ?? '';
        $role_id         = $params['role_id'];
        $role_name       = $params['role_name'] ?? '';
        $role_level      = $params['role_level'];
        $game_channel_id = $params['game_channel_id'] ?? 0;
        $game_channel_id = GameChannelService::getInstance()->checkAndGetId($game_id, $channel, $game_channel_id);
        $goods_type      = Orders::GOODS_TYPE_NORMAL;
        $unique_id       = UserRoleUniqueIdService::getInstance()->getOrCreateUniqueId($user_id, $server_id, $role_id);

        // 校验支付
        $can_pay = PayService::getInstance()->canPay($game_id, $game_channel_id);
        if (!$can_pay) {
            return yqerr(6003);
        }

        // 渠道处理对象
        $sdkobj = SdkBase::loadSDK($game_id, $channel, $game_channel_id);
        if (!$sdkobj) {
            return yqerr(6002);
        }

        // 校验用户
        $user = Users::find($user_id);
        if (!$user) {
            return yqerr(6004);
        }

        // 获取渠道商品，如果存在配置则沿用渠道商品金额
        $channel_goods = GameChannelGoodsId::whereRaw("game_id={$game_id} AND channel={$channel}")->where('goods_id', $goods_id)->first();
        if ($channel_goods && $channel_goods->amount > 0) {
            $money = $channel_goods->amount;
            $goods_type = $channel_goods->goods_type;
        }
        // 部分游戏写死0.1折
        if (in_array($game_id, [1012,1013]) && $channel == 17) {
            $money = $amount * 0.01;
        }

        // 订单落地
        $trade_no               = YqExtend::uniqid();
        $order                  = new Orders;
        $order->trade_no        = $trade_no;
        $order->game_trade_no   = $game_trade_no;
        $order->amount          = $amount;
        $order->money           = $money;
        $order->user_id         = $user->user_id;
        $order->package_id      = $package_id;
        $order->game_id         = $game_id;
        $order->channel         = $channel;
        $order->game_channel_id = $game_channel_id;
        $order->channel_openid  = $user->channel_openid;
        $order->goods_id        = $goods_id;
        $order->goods_name      = $goods_name;
        $order->goods_type      = $goods_type;
        $order->server_id       = $server_id;
        $order->server_name     = $server_name;
        $order->role_id         = $role_id;
        $order->role_name       = $role_name;
        $order->role_level      = $role_level;
        $order->role_unique_id  = $unique_id;

        $order->create_time = time();
        $order->status      = Orders::PAY_STATUS_CREATE;
        $order->ip          = YqExtend::getIp();

        SdkService::getInstance()->supplementDevice($order, $params);
        $order->save();

        // 渠道初始化
        $sdk_info  = $sdkobj->payInit($order, $request);

        $out['sdk_info']     = $sdk_info ?? [];
        $out['trade_no']     = $trade_no;
        $out['callback_url'] = $sdkobj->callbackUrl();
        if (intval($params['amount']) == $params['amount']) {
            $params['amount'] = strval(intval($params['amount']));
        }
        $params['money'] = $money;
        $out['params'] = $params;

        return yqok($out);
    }

    public function callbackToClient(Request $request, $game_channel_id)
    {
        return $this->callback($request, $game_channel_id, 'client');
    }

    // 充值回调
    public function callback(Request $request, $game_channel_id, $cb_type = 'server')
    {
        $game_channel = GameChannelService::getInstance()->get($game_channel_id);
        if (empty($game_channel)) {
            return yqerr(6006);
        }

        $game_id = $game_channel['game_id'];
        $channel = $game_channel['channel'];

        $sdkobj = SdkBase::loadSDK($game_id, $channel, $game_channel_id);
        if (!$sdkobj) {
            return yqerr(6007);
        }

        // 记录请求日志
        $logcb                  = new LogPayCb;
        $logcb->create_time     = time();
        $logcb->game_id         = $game_id;
        $logcb->channel         = $channel;
        $logcb->game_channel_id = $game_channel['id'];
        $logcb->ip              = YqExtend::getIP();
        $logcb->url             = $request->fullUrl();
        $logcb->method          = $request->method();
        $logcb->data            = json_encode($request->post());
        $logcb->input_data      = file_get_contents('php://input');
        $logcb->save();

        // 处理充值回调
        $notify = $sdkobj->payCb($request, $cb_type);
        if ($notify->errno > 0) {
            return $sdkobj->payErr();
        }

        $order    = $notify->order;
        $trade_no = $notify->tradeNo;

        // 找不到我方订单数据
        if (!$order) {
            $notify->errno = 6008;
            return $sdkobj->payErr();
        }

        // 如果订单的渠道信息与回调的渠道信息对应不上，则认为存在跨渠道充值
        if ($game_id != $order->game_id || $channel != $order->channel) {
            $notify->errno = 6009;
            return $sdkobj->payErr();
        }

        // 已经是支付成功的 直接返回告诉支付渠道
        if ($order->status !== Orders::PAY_STATUS_CREATE && $order->status !== Orders::PAY_STATUS_RUNING) {
            return $sdkobj->payOk();
        }

        // 校验商品金额
        $goods_id      = $order->goods_id;
        $channel_goods = GameChannelService::getInstance()->getGoodsId($game_id, $channel, $goods_id);
        if ($channel_goods && $channel_goods->amount != $order->amount) {
            $notify->errno = 6010;
            $sdkobj->payErr();
        }

        // 更改订单状态
        $order->status           = Orders::PAY_STATUS_PAY_OK;
        $order->payok_time       = time();
        $order->channel_trade_no = $notify->channelTradeNo;
        $order->cb_type          = $cb_type;
        $sdkobj->supplementOrderInfo();
        $order->save();

        // 支付成功后处理其他附加任务
        PaySuccessQueue::dispatch($trade_no)->onQueue('default');

        // 通知服务端发货由定时器进行，此处直接返回成功告诉充值渠道
        PayGameCbQueue::dispatch($trade_no, $order->status)->onQueue('high');

        return $sdkobj->payOk();
    }

    public function orderCallClient(Request $request)
    {
        $params = $request->all();

        // 校验签名
        $ret = SdkService::getInstance()->checkSign($params);
        if ($ret === false) {
            return yqerr(101);
        }

        $user_id = $params['user_id'];
        $list = OrdersCallClientService::getInstance()->getAndUpdateCallInfo($user_id);

        return yqok($list);
    }
}
